﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace System
{
    public static class EnvironmentExtension
    {
        /// <summary>
        /// 从Owin中提取所需的请求信息
        /// </summary>
        /// <param name="environment">Owin参数</param>
        public static NFinal.Owin.Request GetRequest(this IDictionary<string, object> environment)
        {
            NFinal.Owin.Request request = new NFinal.Owin.Request();
            request.remoteIpAddress = (string)environment["server.RemoteIpAddress"];
            request.environment = environment;
            request.headers = (IDictionary<string, string[]>)environment["owin.RequestHeaders"];
            request.cookies = new Dictionary<string, string>();
            if (request.headers.ContainsKey("Cookie"))
            {
                string[] tempArray = request.headers["Cookie"][0].Split('&', '=');
                if ((tempArray.Length & 1) == 0)
                {
                    int len = tempArray.Length >> 1;
                    int i = 0;
                    while (i < len)
                    {
                        request.cookies.Add(tempArray[i << 1], Uri.UnescapeDataString(tempArray[(i << 1) + 1]));
                        i++;
                    }
                }
            }
            request.stream = (Stream)environment["owin.RequestBody"];
            //请求参数
            request.requestPath = (string)environment["owin.RequestPathBase"] + (string)environment["owin.RequestPath"];
            //获取二级域名
            string host = request.headers["Host"][0];
            string[] hostName = host.Split('.');
            request.subdomain = hostName.Length == 3 ? hostName[0] : "www";
            request.get = new NFinal.NameValueCollection();
            request.files = null;
            //获取POST方法
            string methodTypeTemp = (string)environment["owin.RequestMethod"];
            switch (methodTypeTemp)
            {
                case "POST": request.methodType = NFinal.MethodType.POST; break;
                case "GET": request.methodType = NFinal.MethodType.GET; break;
                case "DELETE": request.methodType = NFinal.MethodType.DELETE; break;
                case "PUT": request.methodType = NFinal.MethodType.PUT; break;
                case "AJAX": request.methodType = NFinal.MethodType.AJAX; break;
                default: request.methodType = NFinal.MethodType.NONE; break;
            }
            //提取内容类型
            if (request.methodType == NFinal.MethodType.POST)
            {
                NFinal.ContentType contentType = NFinal.ContentType.NONE;
                string contentTypeString = null;
                if (request.headers.ContainsKey("Content-Type"))
                {
                    contentTypeString = request.headers["Content-Type"][0];
                    switch (contentTypeString.Split(';')[0])
                    {
                        case "multipart/form-data": contentType = NFinal.ContentType.Multipart_form_data; break;
                        case "text/json":
                        case "application/json": contentType = NFinal.ContentType.Application_json; break;
                        case "application/x-www-form-urlencoded": contentType = NFinal.ContentType.Application_x_www_form_urlencoded; break;
                        case "application/xml":
                        case "text/xml": contentType = NFinal.ContentType.Text_xml; break;
                        default: contentType = NFinal.ContentType.NONE; break;
                    }
                }
                //提取form参数
                if (request.stream != System.IO.Stream.Null)
                {
                    if (contentType == NFinal.ContentType.Application_x_www_form_urlencoded)
                    {
                        System.IO.StreamReader sr = new System.IO.StreamReader(request.stream);
                        string body = sr.ReadToEnd();
                        sr.Dispose();
                        if (!string.IsNullOrEmpty(body))
                        {
                            string[] formArray = body.Split('&', '=');
                            if (formArray.Length > 1 && (formArray.Length & 1) == 0)
                            {
                                for (int i = 0; i < formArray.Length; i += 2)
                                {
                                    request.get.Add(formArray[i], NFinal.Utility.UrlDecode(formArray[i + 1]));
                                }
                            }
                        }
                    }
                    //else if (contentType == NFinal.ContentType.Text_xml)
                    //{
                    //    System.IO.StreamReader sr = new System.IO.StreamReader(stream);
                    //    string body = sr.ReadToEnd();
                    //    sr.Dispose();
                    //    if (!string.IsNullOrEmpty(body))
                    //    {
                    //        System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
                    //        doc.LoadXml(body);
                    //        if (doc.DocumentElement != null)
                    //        {
                    //            foreach (System.Xml.XmlElement xmlNode in doc.DocumentElement.ChildNodes)
                    //            {
                    //                get.Add(xmlNode.Name, xmlNode.Value);
                    //            }
                    //        }
                    //    }
                    //}
                    else if (contentType == NFinal.ContentType.Application_json)
                    {
                        System.IO.StreamReader sr = new System.IO.StreamReader(request.stream);
                        string body = sr.ReadToEnd();
                        sr.Dispose();
                        NFinal.Json.IJsonSerialize serializable = new NFinal.Json.NewtonsoftJsonSerialize();
                        IDictionary<string, object> data = serializable.DeserializeObject<IDictionary<string, object>>(body);
                        foreach (var ele in data)
                        {
                            request.get.Add(ele.Key, ele.Value.ToString());
                        }
                    }
                    else if (contentType == NFinal.ContentType.Multipart_form_data)
                    {
                        //multipart/form-data
                        string boundary = NFinal.Owin.HttpMultipart.HttpMultipart.boundaryReg.Match(contentTypeString).Value;
                        var multipart = new NFinal.Owin.HttpMultipart.HttpMultipart(request.stream, boundary);
                        request.files = new Dictionary<string, NFinal.Owin.HttpMultipart.HttpFile>();
                        foreach (var httpMultipartBoundary in multipart.GetBoundaries())
                        {
                            if (string.IsNullOrEmpty(httpMultipartBoundary.Filename))
                            {
                                string name = httpMultipartBoundary.Name;
                                if (!string.IsNullOrEmpty(name))
                                {
                                    string value = new System.IO.StreamReader(httpMultipartBoundary.Value).ReadToEnd();
                                    request.get.Add(name, value);
                                }
                            }
                            else
                            {
                                request.files.Add(httpMultipartBoundary.Name, new NFinal.Owin.HttpMultipart.HttpFile(httpMultipartBoundary));
                            }
                        }
                    }
                }
            }
            request.queryString = (string)environment["owin.RequestQueryString"];
            //提取URL?后的参数
            if (request.queryString.Length > 0)
            {
                string[] queryArray = request.queryString.Split('&', '=');
                if (queryArray.Length > 1 && (queryArray.Length & 1) == 0)
                {
                    for (int i = 0; i < queryArray.Length; i += 2)
                    {
                        request.get.Add(queryArray[i], NFinal.Utility.UrlDecode(queryArray[i + 1]));
                    }
                }
            }
            return request;
        }
        /// <summary>
        /// 把Response输出到前端
        /// </summary>
        /// <param name="environment"></param>
        /// <param name="response"></param>
        public static void WriteResponse(this IDictionary<string, object> environment, NFinal.Owin.Response response)
        {
            environment["owin.ResponseStatusCode"] = response.statusCode;
            IDictionary<string, string[]> headers = (IDictionary<string, string[]>)environment["owin.ResponseHeaders"];
            if (response.headers.Count > 0)
            {
                foreach (var header in response.headers)
                {
                    headers.Add(header.Key, header.Value);
                }
            }
            response.stream.CopyTo((Stream)environment["owin.ResponseBody"]);
            response.stream.Close();
        }
    }
}
